---
--类名: BattleManager.lua
--创建日期: 2017-8-30
--创建人: 陈小虎
--功能描述:
--修改内容:
--修改日期:
--修改人:
--修改备注:
--
local BattleController = require("app.battleV3.BattleController")
local BattleInfoNormal = import("..models.vo.BattleInfoNormal")
local BattleInfoArena = import("..models.vo.BattleInfoArena")
local Armature = require("app.public.avatar.Armature")

local socket = require("socket")

local BattleCore_enqueue = battle.BattleCore.enqueue
local BattleCore_progress = battle.BattleCore.progress
local BattleCore_getCurrentTime = battle.BattleCore.getCurrentTime

local ProgressResult_getFinished = battle.ProgressResult.getFinished
local ProgressResult_getBattleResult = battle.ProgressResult.getBattleResult
local BattleResult_wonTeamId = battle.BattleResult.wonTeamId
local BattleResult_frameCount = battle.BattleResult.frameCount
local Command_getActualTime = battle.Command.getActualTime

local NodeGetPositionXFunc = cc.Node.getPositionX
local MathFloor = math.floor

local TeamModel

local battleTest = false

local BattleManager = class("BattleManager")

function BattleManager:isSingleMode()
    return self.flagSingleMode
end

function BattleManager:setSingleMode(flag)
    self.flagSingleMode = flag
end

function BattleManager:isEscapeInSingleMode()
    return self.flagEscapeInSingleMode
end

function BattleManager:setEscapeInSingleMode(flag)
    self.flagEscapeInSingleMode = flag
end

function BattleManager:getSingleStartDataType()
    return self.typeSingleStartData
end

function BattleManager:getSingleModeStartData()
    return self.singleModeStartMsg, self.singleModeStartRawData
end

function BattleManager:clearSingleModeStartData()
    self.typeSingleStartData = nil
    self.singleModeStartMsg = nil
    self.singleModeStartRawData = nil
end

function BattleManager:getPauseBattleDelta()
    return self.pauseBattleDelta
end

function BattleManager:clearPauseBattleDelta()
    self.pauseBattleDelta = 0
end

function BattleManager:ctor()
    cc(self):addComponent("components.behavior.EventProtocol"):exportMethods()

    -- 战斗初始化中，gotoBattle-战斗所需准备好-战斗开始
    self._isInBattleInit = false
end

function BattleManager:toStringEx(value)
    if type(value)=='table' then
        return self:tableToStr(value)
    elseif type(value)=='string' then
        return "\'"..value.."\'"
    else
        return tostring(value)
    end
end

function BattleManager:tableToStr(t)
    if t == nil then return "" end
    local retstr= "{"

    local i = 1
    for key,value in pairs(t) do
        local signal = ","
        if i==1 then
          signal = ""
        end

        if key == i then
            retstr = retstr..signal..self:toStringEx(value)
        else
            if type(key)=='number' or type(key) == 'string' or type(key) == "boolean" then
                retstr = retstr..signal..'['..self:toStringEx(key).."]="..self:toStringEx(value)
            else
                if type(key)=='userdata' then
                    retstr = retstr..signal.."*s"..self:tableToStr(getmetatable(key)).."*e".."="..self:toStringEx(value)
                else
                    retstr = retstr..signal..key.."="..self:toStringEx(value)
                end
            end
        end

        i = i + 1
    end

     retstr = retstr.."}"
     return retstr
end

function BattleManager:strToTable(str)
    if str == nil or type(str) ~= "string" then
        return
    end

    return loadstring("return "..str)()
end

function BattleManager:readfile(path)
    if cc.FileUtils:getInstance():isFileExist(path) then
        local fullPath = cc.FileUtils:getInstance():fullPathForFilename(path)
        return cc.HelperFunc:getFileData(fullPath)
    end
    return nil
end

function BattleManager:writefile(path, content, mode)
    mode = mode or "wb"
    local file = io.open(path, mode)
    if file then
        if file:write(content) == nil then return false end
        io.close(file)
        return true
    else
        return false
    end
end

function BattleManager:init()
    TeamModel = app:getInst("TeamModel")

    local armatureName = Res.BattleEnterEffectName
    local armatureNamePath = Res.BattleEnterEffectPath
    local effectArmature = Armature.create({path=armatureNamePath,armatureName=armatureName,animationName="",skeletonName=armatureName})
    local scale = math.min((display.width - display.safe_x * 2) / display.ui_width, (display.height - display.safe_y * 2) / display.ui_height)
    effectArmature:setScaleX(scale) -- iphoneX适配
    effectArmature:setScaleY(scale)
    effectArmature:setPosition(cc.p(display.width/2,display.height/2))
    self:getParent():addChild(effectArmature,SceneZOrder.battleLayerZOrder+2)
    self.effectArmature = effectArmature
    self.effectArmature:setVisible(false)

    self.flagSingleMode = false
    self.pauseBattleTime = 0
    self.pauseBattleDelta = 0
    self._cronsIdx = nil
    --强制清空
    app:addEventListener("FORCE_QUIT",function()
        self:goOutBattle(false)
    end)
end

function BattleManager:clear()
    self:setBattle(false)
    self:waitBattle(false)
end

-- 都有对战双方的loading信息, 当前地图和发生战斗的地图不一样才需要loading，一样不需要loading
function BattleManager:onParseEnterArenaBattle(msg, isShowLoading)
    if MapManager:isEnterGame() then
        self._enterBattleInfo = BattleInfoArena.new(msg)
        
        -- 地图不一样，在切换地图中，需要loading
        local curMapId = MapManager:getMapId()
        local bChangingMap = (MapManager:isChangeMap() or curMapId ~= msg.mapId)

        if bChangingMap then
            UIHandler:handleMessage({id = Constant.FUNC_TYPE_ARENA_VS,mode = "open",data = self._enterBattleInfo})
            -- 如果是冠军赛\跨服公会战战斗的加载，就不显示loading界面的提示文字
            if self._enterBattleInfo:getBattleType() == Enums.EBattleType.BtType_Throne then
                UIHandler:hideArenaVsNotice()
            end
        else
            -- arena战斗已经在地图中，直接开始战斗
            MapManager:getMap():setZoomScale(Constant.BattleEnterMapDefaultCameraScale)
            if isShowLoading then
                UIHandler:handleMessage({id = Constant.FUNC_TYPE_ARENA_VS,mode = "open",data = self._enterBattleInfo})
                -- 如果是冠军赛\跨服公会战战斗的加载，就不显示loading界面的提示文字
                if self._enterBattleInfo:getBattleType() == Enums.EBattleType.BtType_WorldGuildWar then
                    UIHandler:hideArenaVsNotice()
                end
            end
            self:prepareBattle()
        end
    else
        -- 还没有进入游戏就触发了竞技场战斗，先缓存数据
        self._enterArenaMsg = msg
    end
end

function BattleManager:onParseEnterArenaBattlePre(msg)    
    local enterBattleInfo = BattleInfoArena.new(msg)
    enterBattleInfo.isMelee = true

    UIHandler:handleMessage({id = Constant.FUNC_TYPE_ARENA_VS,mode = "open",data = enterBattleInfo})
end

-- self._enterBattleInfo 是BattleInfoArena or BattleInfoNormal
function BattleManager:intoBattleAfterEnterMap()
    if self._enterArenaMsg then
        self:onParseEnterArenaBattle(self._enterArenaMsg)
        self._enterArenaMsg = nil
    else
        local mapId = MapManager:getMapId()
        if self._enterBattleInfo and self._enterBattleInfo:getMapId() == mapId then
            MapManager:getMap():setZoomScale(Constant.BattleEnterMapDefaultCameraScale)
            self:prepareBattle()
        end
    end
end

function BattleManager:setParent(parent)
	self._parent = parent
end

function BattleManager:getParent()
	return self._parent
end

function BattleManager:setBattle(isBattle)
    self._battle = isBattle
end

function BattleManager:isBattle()
    return self._battle
end

function BattleManager:waitBattle(wait)
    self._waitBattle = wait
end

function BattleManager:isWaitBattle()
    return self._waitBattle
end

function BattleManager:isInBattle()
    if self:isWaitBattle()
      or self:isBattle() then
        return true
    end
    return false
end

-- 战斗入口
function BattleManager:prepareBattle(isReconnected)
    local enterBattleInfo = self._enterBattleInfo
    if enterBattleInfo == nil then
        return
    end

    local character = FieldManager:getMyCharacter()
    if character == nil then
        return
    end

    self:clearClientWeakEndCB()

    -- 进入战斗后停止同步地图移动(有可能是服务器主动下发的开始战斗，比如 赏金任务，公会战，所以这里要加上这两段)
    self:noMove()
    FieldManager:setStopSendPosition(true)

    -- 战斗准备过程中屏蔽触摸输入
    UIHandler:addPrepareBattleTouchMask()
    UIHandler:removeAllUI()
    UIHandler:hideDesktop()

    -- 清空pvp上局结算数据
    app:sendMsg("PvpController", "clearPvpResultData")

    -- 取消采集行为
    if DoEventHandler.isDoGatherAction() then
        DoEventHandler.setStopGatherAction(true)
    end

    FieldManager:characterStopMove()
    FieldManager:breakTransferStatus()
    FieldManager:hideTaskFollowMercenarys()

    if DungeonManager:isInDungeon() then
        FieldManager:setFollowCharactersBattleMark(true)
    end

    MapManager:setFocusCharacterNotInit({character = character})
    FieldManager:updateAllCharactersUpHead(false)
    MapManager:pauseRunCameraZoomForEvent(true)
    NpcManager:stopUpdateNpcPlayEvents(true)
    NpcManager:resetAllNpcEventStatus()
    NpcManager:allNpcAbslutelyVisibility(false)

    self:waitBattle(true)

    self:addBattleEndListener(enterBattleInfo, isReconnected)

    FieldManager:charactersPrepareBattle()
end

function BattleManager:getBattleTeamMembers()
    if self.mBattleController then
        return self.mBattleController:getBattleTeamMembers()
    end
    return nil
end

-- 在快进或者战斗准备阶段算是busy
function BattleManager:isBattleBusy()
    if not cc.isDead(self.mBattleController) then
        return self._isInBattleInit or self.mBattleController:isFastForward()
    end
    return false
end

function BattleManager:gotoBattle(battleId, host, port, battleCreateParams)
    if not MapManager:getWorld() then
        NpcManager:stopUpdateNpcPlayEvents(false)
        return
    end

    UIHandler:hideIMBubble()
    FieldManager:hideAllBubble()
    local character = FieldManager:getPuppetCharacter()
    if not character then
        character = FieldManager:getMyCharacter()
    end
    if not character then
        NpcManager:stopUpdateNpcPlayEvents(false)
        self:goOutBattle()
        return
    end

    if self:isBattle() then
        self:goOutBattle(nil,nil,true)
    end

    if not self:isWaitBattle() then
        UIHandler:hideDesktop()
    end

    DoEventHandler.setCurrrentMark(nil)

    MapManager:fadeMapNode({time=0.5,back=false})

    FieldManager:followMercenaryVisibility(false)

    StoryManager:pauseStoryModeMask()

    DoEventHandler.setTracking(false)

    DoEventHandler.setOpenUI(false)
    self:clearClientWeakEndCB()
    self:setBattle(true)

    self:waitBattle(false)

    FieldManager:showMainCharacterInBattle(true)
    FieldManager:hideTaskFollowMercenarys()

    FieldManager:stopTouch(true)

    DoEventHandler.skipStoryViewVisibility(false)
    if not NpcManager:isFadeNpcsForBattle() then
        NpcManager:allNpcAbslutelyVisibility(false)
    end

    UIHandler:removeAllUI(true)
    UIHandler:reorderSystemUIToBattle()

    FieldManager:getWeatherSystem():closeWeather()

    -- app:sendMsg("IMRoomController", "hideView")
    UIHandler:hideChatUI()

    local function toBattle()
        local map = MapManager:getMap()
        local characterScale = MapManager:getGroundRoleScale()
        local npcScale = MapManager:getGroundNpcScale()
        local bossScale = MapManager:getGroundBossScale()
        local mecScale = MapManager:getGroundMercenaryScale()
        -- Character scene pos is about 568 (half of display.width)
        local mainCharacterPosX = MapManager:getMainCharacterPosX()
        print("======>toBattle mainCharacterPosX:", mainCharacterPosX)

        local battleNormalColor = map:getBattleNormalColor()--cc.c4b(150,150,150,255)
        local deadColor = battleNormalColor

        local function mapBackToNormal()
            MapManager:mapToNormalColor()
        end

        local function mapInBattleNormal()
            MapManager:mapToNormalColor()
        end

        local function mapInBattleMoreMidBlack()
            map:toBattleMoreMidBlack()
        end

        local function mapInBattleFullBlack()
            map:toBattleFullBlack()
        end

        local function mapInBattleMoreBlack()
            map:toBattleMoreBlack()
        end

        local function onLastEntityDie()
            mapInBattleMoreBlack()
        end

        local function LastEntityDieEnd()
            mapInBattleNormal()
        end

        local function showBattle()
            if self.mBattleController then
                self.mBattleController:setVisible(true)
            end
        end

        local function hideBattle()
            if self.mBattleController then
                self.mBattleController:setVisible(false)
            end
        end

        local function onEnemySuperSkillRelease(event)
            mapInBattleMoreMidBlack()
        end

        local function onSuperSkillRelease(event)
            mapInBattleMoreBlack()
        end

        local function onRecoverMapColorToNoraml()
            mapInBattleNormal()
        end

        --战斗初始化开始
        local function onBattleInit(battleScale)
            -- 战斗准备过程结束后取消对触摸输入的屏蔽
            UIHandler:removePrepareBattleTouchMask()

            mapInBattleNormal()
            showBattle()
            FieldManager:showMainCharacterInBattle(false)
            FieldManager:startHideCharacters(true)
        end

        --战斗开始
        local function onBattleBegan(leftClampPosX,rightClampPosX)
            self._isInBattleInit = false
            MapManager:setBattleCameraClamp({leftClampPosX = leftClampPosX, rightClampPosX = rightClampPosX})
            map:stopAllSounds(false)
            DungeonManager:hideAllBNpcs()
            -- 进入战斗音效
            AM.playSoundById(9283)
        end

        local function onSetMapFocusActor(actor, needInit)
            MapManager:setFocusBattleActor({actor = actor, needInit = needInit})
        end

        --战斗结束
        local function onBattleResult(iswon,playerMovedX)
            print("---onBattleResult--- iswon",iswon,"playerMovedX",playerMovedX)

            self._playerMovedX = playerMovedX

            local resultSfx = iswon and Res.BattleWonSound or Res.BattleLoseSound
            AM.play(resultSfx, false)
        end

        local function onBattleScale(event)
            local battleScale = event.scale
            local zoomLayer = map.mZoomLayer
            local zoomScale = zoomLayer:getScale()

            local speed = 1.0
            local time = math.abs((battleScale - zoomScale)/speed)
            if zoomLayer:getNumberOfRunningActions() > 0 then
                time = 0
            end

            MapManager:forecCameraZoomOutToDest({time = time,dstScale = battleScale,flag = "battle"})
        end

        local function openFunction(event)
            local functionId = event.functionId
            local desktopController = UIHandler:getDesktopController()
            desktopController:openFunction(functionId)
        end

        local function checkBattleState()
            local function S2C_QueryBattleState(msg)
                if msg then
                    if msg.battleId then
                        local serverbattleId = msg.battleId
                        local serverBattleUrl = msg.battleUrl
                        --print("====S2C_QueryBattleState serverbattleId:",serverbattleId)
                        --如果游戏服在战斗中
                        if self:isBattle() then
                            --如果本地在战斗中
                            if battleId ~= serverbattleId then
                                --如果不是同一场战斗
                                --todo 几乎不可能发生，此处也无法处理
                            else
                                --如果是同一场战斗
                                --do nothing
                            end
                        else
                            --如果不在战斗中
                            --todo 此处无法处理
                        end
                    else
                        --如果游戏服不在战斗中
                        if self:isBattle() then
                            --如果本地在战斗中
                            --print("====S2C_QueryBattleState")
                            self:goOutBattle()
                        else
                            --如果不在战斗中
                            --do nothing
                        end
                    end
                end
            end
            app.session:request("pb_query.C2S_QueryBattleState",{},S2C_QueryBattleState)
        end

        local function onBattleChatUiSetting(event)
            local visible = event.visible
            if visible then
                UIHandler:showChatUI()
            else
                UIHandler:hideChatUI()
            end
        end

        if not self.mBattleUiLayer then
            self.mBattleUiLayer = display.newLayer()
            self.mBattleUiLayer:setTouchSwallowEnabled(false)
            self:getParent():addChild(self.mBattleUiLayer, SceneZOrder.battleLayerZOrder)
        end

        if not self.mBattleFloatUiLayer then
            self.mBattleFloatUiLayer = display.newLayer()
            self.mBattleFloatUiLayer:setTouchSwallowEnabled(false)
            self:getParent():addChild(self.mBattleFloatUiLayer,SceneZOrder.battleLayerZOrder + 1)
        end

        local maskRootLayer = map:createBattleMaskLayer()

        local tFormationId
        if self._enterBattleInfo then
            tFormationId = self._enterBattleInfo:getFormationId()
        end

        local params =
        {
            uiLayer = self.mBattleUiLayer,
            uiFloatLayer = self.mBattleFloatUiLayer,
            mapRoot = map,
            maskRootLayer = maskRootLayer,
            formationId = tFormationId,
            deadColor = deadColor,
            altitude = 0,
            scales =
            {
                characterScale = characterScale,
                npcScale = npcScale,
                bossScale = bossScale,
                mecScale = mecScale

            },
            mainCharacterPosX = mainCharacterPosX,
            mapId = MapManager:getMapId()
        }

        self.mBattleController = BattleController.createWithUrl(host,port,battleCreateParams,params)

        local battleController = self.mBattleController

        battleController:initParams()

        hideBattle()

        battleController:addEventListener("GameResult",onBattleResult)
        battleController:addEventListener("GameInit",onBattleInit)
        battleController:addEventListener("LastEntityDie",onLastEntityDie)
        battleController:addEventListener("LastEntityDieEnd",LastEntityDieEnd)
        battleController:addEventListener("BattleScale",onBattleScale)
        battleController:addEventListener("SuperSkillRelease",onSuperSkillRelease)
        battleController:addEventListener("EnemySuperSkillRelease",onEnemySuperSkillRelease)
        battleController:addEventListener("RecoverMapColor",onRecoverMapColorToNoraml)
        battleController:addEventListener("MapFullBlack",mapInBattleFullBlack)
        battleController:addEventListener("ChatUiVisible",onBattleChatUiSetting)
        battleController:addEventListener("GameBegan",onBattleBegan)
        battleController:addEventListener("checkBattleState",checkBattleState)
        battleController:addEventListener("OpenFunction",openFunction)
        battleController:addEventListener("SetMapFocusActor", onSetMapFocusActor)

        map:addBattleNodeToMap(battleController)

        battleController:initScaleParam()

        if self:isSingleMode() then
            self.mBattleController:BeginSingleGame()
        end
    end

    local function toCenterOver()
        MapManager:pauseRunCameraZoomForEvent(true)
        MapManager:stopParallaxActions()
        toBattle()
        MapManager:stopCameraForBattle({stop = false})
    end

    self._isInBattleInit = true

    MapManager:stopCameraForBattle({stop = true})
    MapManager:backMapOffsetToCenter({time = 0.1,callback = toCenterOver})
end

function BattleManager:goOutBattle(iswon,loots,onlyBattle)
    if not self.mBattleController then return end

    self.flagSingleMode = false
    self:clearSingleModeStartData()

    -- DungeonManager:stopPlayDungeonEvent(iswon)
    self._isInBattleInit = false
    self:setBattle(false)
    self:waitBattle(false)
    FieldManager:characterStopMove()
    FieldManager:characterForceStandby()
    FieldManager:showTaskFollowMercenarys()
    FieldManager:setFollowCharactersBattleMark(false)
    FieldManager:updateAllCharactersUpHead(true)
    MapManager:setFocusBattleActor({actor = nil})
    MapManager:mapToNormalColor()
    if not onlyBattle then
        self:doGoOutBattleOperate(iswon)
    end

    local map = MapManager:getMap()
    if cc.isAlive(map) then
        map:removeBattleNodeFromMap()
        map:removeBattleMaskNodeFromMap()
    end
    MapManager:playMapMusic()

    self.mBattleController = nil
    self._enterBattleInfo = nil
    FieldManager:setStopSendPosition(false)

    DungeonManager:showAllBNpcs()
    TaskManager:startDelayFollowUpTaskEvents()

    EM:notify("onGoOutBattle")

    if DungeonManager:isRace() then
        EM:notify("onSkillChangeNodeChanged", {status = "show"})
    end
end

function BattleManager:doGoOutBattleOperate(iswon)
    UIHandler:removePrepareBattleTouchMask()

    StoryManager:resumeStoryModeMask()
    self:getParent():showInfoGetAfterBattle()
    DoEventHandler.skipStoryViewVisibility(true)
    UIHandler:reorderSystemUIToNormal()

    if not DoEventHandler.DoTaskBattleEvent then
        -- TODO 补丁，歌剧院不显示自己形象，把和玩家显示相关的添加条件
        local isInTheatre = app:sendMsg("TheatreModel", "isTheatreMap")
        if not isInTheatre then
            UIHandler:showDesktop()
        end

        MapManager:fadeMapNode({time=0.5,back=true})
        MapManager:pauseRunCameraZoomForEvent(false)
        if not isInTheatre then
            MapManager:setFocusCharacterForInit({character = FieldManager:getMyCharacter()})
        end
        MapManager:pauseAdjustCamera(false)

        NpcManager:allNpcAbslutelyVisibility(true)
        if NpcManager:isFadeNpcsForBattle() then
            NpcManager:fadeInAllNpcs(0.2)
            FieldManager:fadeInAllCharacters(0.2)
            NpcManager:setFadeNpcsForBattle(false)
        end
        NpcManager:stopUpdateNpcPlayEvents(false)

        FieldManager:stopTouch(false)
        if not isInTheatre then
            FieldManager:stopHideCharacters()

            FieldManager:forceShowMainCharacter()
            FieldManager:exceptSelfCharactersVisibility(true)
            FieldManager:fadeCharacter(true,true,FieldManager:getMyCharacter(),1.0)
            FieldManager:followMercenaryVisibility(true)
            FieldManager:excuteAutoWayFindingParams()
        end
    else
        FieldManager:setMainCharacterOpacity(255)
        if iswon then
            UIHandler:hideDesktop()
            -- app:sendMsg("IMRoomController", "hideView")
            DoEventHandler.nextEventsVec(DoEventHandler.CurTaskBattleEvent)
            DoEventHandler.CurTaskBattleEvent = nil
        else
            DoEventHandler.CurTaskBattleEvent = nil
            StoryManager:clearTransferStatus()
        end
    end
end

function BattleManager:onParseEndBattle(msg)
    app:dispatchEvent({name="EVENT_BATTLE_END",id=msg.id,data=msg})
end

function BattleManager:addBattleEndListener(enterBattleInfo, reconnect)
    if not enterBattleInfo
      or not enterBattleInfo.id
      or not enterBattleInfo.url
      or string.len(enterBattleInfo.url) <= 0 then
        if reconnect then
            self:goOutBattle()
        else
            self:goOutBattle(nil,nil,true)
        end
        return
    end

    print("Enter Battle Info:id = ", enterBattleInfo.id, "url = ", enterBattleInfo.url)

    local uid = app.session.uid
    local token = app.session.token
    local battleVer = battle.BattleResConfig:getInstance():getBattleVersion()
    local battleConfigVer = battle.BattleConfig:getInstance():getChecksum()

    local battleId = enterBattleInfo.id
    local battleAuthCode = enterBattleInfo.authCode or ""
    local _1,host,port,path = string.parseUrl(enterBattleInfo.url)
    local battleCreateParams =
    {
        battleID =  battleId,
        token = token,
        btVer = battleVer,
        cfgVer = battleConfigVer,
        authCode = battleAuthCode,
        uid = uid,
        battlePath = path
    }

    -- GemService 监测战斗场景开始
--    local zoneId = app.session:getZoneId()
--    local mapId = enterBattleInfo.mapId or MapManager:getMapId() or "none"
--    local tp = enterBattleInfo.btType or "none"
--    GemService:start(zoneId, mapId .. ":" .. tp, enterBattleInfo.url)

    local function BattleEndListener(event)
        -- GemService 监测战斗场景结束
--        GemService:endLua()
        local id = event.id
        if battleId == id then
            app:removeEventListener(self._endHandler)
            self._endHandler = nil
            --如果失败
            local data = event.data
            local isWon = data.won or false
            local loots = data.loots or {}
            local btType = data.btType--0 - PVE， 1- PVP
            local isDungeon = data.isDungeon
            local rewardLimit = data.rewardLimit

            -- for i=1,#loots do
            --     local loot = loots[i]
            --     --print("====>loot "..i,"type:"..loot.type,"id:"..loot.id,"num:"..loot.num)
            -- end

            local function clearFailedOperation()
                FieldManager:clearAutoWayFindingParams()
            end

            if isDungeon then
                if isWon then
                    DungeonManager:resetBattleStatus()
                    --TODO : 地图不够大 会有bug 临时关闭
                    --[[
                    if self._playerMovedX then
                        local character = FieldManager:getMyCharacter()
                        DungeonManager:teleportCharacter(character:getPositionX() + self._playerMovedX)
                    end
                    ]]
                    -- 竞速模式不显示掉落
                    if not DungeonManager:isRace() then
                        DelayStack:pushToFront({name = "dungeonDrop",loots = loots, rewardLimit = rewardLimit})
                    end
                else
                    clearFailedOperation()
                    DungeonManager:failedBattle()
                end
            end

            --世界boss增加掉落显示
            if isWon and btType == Enums.EBattleType.BtType_WorldBoss then
                DelayStack:pushToFront({name = "dungeonDrop", loots = loots, rewardLimit = rewardLimit})
            end

            -- if not isWon and btType == 0 then
            if not isWon then
                local isShow = false

                if enterBattleInfo.formationId ~= nil then
                    local battleC = GD:queryBattleById(enterBattleInfo.formationId)
                    if battleC and battleC.ID then
                        if tonumber(battleC.battletype) == 0 then
                            isShow = true
                        end
                    end
                end

                if isShow then
                    clearFailedOperation()
                    -- TODO 暂时先这样判断，应该有个玩法id，根据玩法来控制是否弹失败界面
                    -- 歌剧院失败就结束了，不弹战斗结束框
                    if btType ~= Enums.EBattleType.BtType_TheatrePve then
                        DelayStack:pushToFront({name = "battleFailed"})
                    end
                end
            end

            self:goOutBattle(isWon,loots)
            print("------BattleEndListener------")
        end
    end

    local function BattleEndSwitchListener(event)
        self.pvpEventCache = nil
        --判断是否是超时后遇到客户端强制结束
        if event.isClientBattleEnd then
            self:endBattleSwitchOnWeakNetwork()
            return
        end
        self:clearClientWeakEndCB()
        local msgBattleEnd = event.data -- message S2C_BattleEnd
        local btType = msgBattleEnd.btType --0 - PVE， 1- PVP

        if (btType == Enums.EBattleType.BtType_ArenaPvp
          or btType == Enums.EBattleType.BtType_Melee
          or btType == Enums.EBattleType.BtType_Duel
          or btType == Enums.EBattleType.BtType_Throne
          or btType == Enums.EBattleType.BtType_WorldGuildWar)
          and self.mBattleController ~= nil then
            -- PVP战斗MVP展示延迟逻辑
            self.pvpEventCache = event
            local pvphandler
            pvphandler = app:addEventListener("EVENT_BATTLE_PVP_END",function()
                if self.pvpEventCache then
                    BattleEndListener(self.pvpEventCache)
                    app:removeEventListener(pvphandler)
                end
            end)
            if cc.isAlive(self.mBattleController) and not self.mBattleController.isGameOver then
                self.mBattleController:forceGameOver()
            end
        elseif btType == Enums.EBattleType.BtType_TheatrePve then
            -- 歌剧院，在还没gameOver就结束，说明是被动失败，播放失败动画
            if cc.isAlive(self.mBattleController) then
                if not self.mBattleController.isGameOver then
                    self.mBattleController:forceGameOver()

                    local delay1 = cca.delay(3)
                    local cb1 = cca.cb(function() EM:notify("onTheatrePveEnd") end)
                    local delay2 = cca.delay(0.5)
                    local cb2 = cca.cb(function() BattleEndListener(event) end)
                    local action = cca.seq({delay1, cb1, delay2, cb2})
                    self.mBattleController:runAction(action)
                else
                    EM:notify("onTheatrePveEnd")
                    self.mBattleController:performWithDelay(function()
                        BattleEndListener(event)
                    end, 0.5)
                end
            else
                BattleEndListener(event)
            end
        else
            BattleEndListener(event)
        end

        -- 在收到游戏服战斗结束的消息时，如果和战斗服还有网络连接，则主动断开
        if cc.isAlive(self.mBattleController) then
            self.mBattleController:exitBattle()
        end
    end

    if self._endHandler then
        app:removeEventListener(self._endHandler)
        self._endHandler = nil
    end
    self._endHandler = app:addEventListener("EVENT_BATTLE_END",BattleEndSwitchListener)

    self:getParent():performWithDelay(function()
        self:gotoBattle(battleId, host, port, battleCreateParams)
    end, 0.3)

    -- 普通战斗显示进入战斗
    if enterBattleInfo.btType == Enums.EBattleType.BtType_Normal then
        self.effectArmature:setVisible(true)
        self.effectArmature:playAni({
            name = Res.BattleEnterEffectName,
            playTimes = 1,
            completeCallback = function(sender)
                self.effectArmature:setVisible(false)
            end
        })
    end
end

function BattleManager:endBattleOnWeakNetwork()
    if self._endHandler then
        app:removeEventListener(self._endHandler)
        self._endHandler = nil
    end
    FieldManager:clearAutoWayFindingParams()
    DungeonManager:failedBattle()

    self:goOutBattle()
    print("------weaknetwork BattleEndListener------")
end


--在弱联网没有接受到结束信息的环境下结束战斗
function BattleManager:endBattleSwitchOnWeakNetwork()
    local btType = self:getEnterBattleType()

    if (btType == Enums.EBattleType.BtType_ArenaPvp
      or btType == Enums.EBattleType.BtType_Melee
      or btType == Enums.EBattleType.BtType_Duel
      or btType == Enums.EBattleType.BtType_Throne
      or btType == Enums.EBattleType.BtType_WorldGuildWar)
      and self.mBattleController ~= nil then
        if cc.isAlive(self.mBattleController) and not self.mBattleController.isGameOver then
            self.mBattleController:forceGameOver()
        end
        self:endBattleOnWeakNetwork()
    elseif btType == Enums.EBattleType.BtType_TheatrePve then
        if cc.isAlive(self.mBattleController) then
            if not self.mBattleController.isGameOver then
                self.mBattleController:forceGameOver()

                local delay1 = cca.delay(3)
                local cb1 = cca.cb(function() EM:notify("onTheatrePveEnd") end)
                local delay2 = cca.delay(0.5)
                local cb2 = cca.cb(function() self:endBattleOnWeakNetwork() end)
                local action = cca.seq({delay1, cb1, delay2, cb2})
                self.mBattleController:runAction(action)
            else
                EM:notify("onTheatrePveEnd")
                self.mBattleController:performWithDelay(function()
                    self:endBattleOnWeakNetwork()
                end, 0.5)
            end
        else
            self:endBattleOnWeakNetwork()
        end

    else
        self:endBattleOnWeakNetwork()
    end

    -- 在收到游戏服战斗结束的消息时，如果和战斗服还有网络连接，则主动断开
    if cc.isAlive(self.mBattleController) then
        self.mBattleController:exitBattle()
    end
end

function BattleManager:getBattleFaceTo(dir)--dir left or right
    local faceTo = Enums.FaceTo.left
    if dir == "left" then
        faceTo = Enums.FaceTo.right
    elseif dir == "right" then
        faceTo = Enums.FaceTo.left
    else
        local character = FieldManager:getMyCharacter()
        if character then
            if character:isFaceToLeft() then
                faceTo = Enums.FaceTo.left
            else
                faceTo = Enums.FaceTo.right
            end
        end
    end
    return faceTo
end

function BattleManager:battleStart(params)
    local faceTo = self:getBattleFaceTo(params.dir)
    app.session:request("pb_map.C2S_BattleWith",{npcID = tonumber(params.npcID),faceTo = faceTo},params.callback)
end

function BattleManager:noMove()
    FieldManager:stopTouch(true)
    FieldManager:saveAutoWayFindingParams()
    FieldManager:getMyCharacter():stopMove(true)
end

function BattleManager:mineBattleStart(params)
    -- 向服务器上报 停止移动
    -- FieldManager:saveAutoWayFindingParams()
    -- FieldManager:getMyCharacter():stopMove(true)
    self:noMove()
    
    local faceTo = self:getBattleFaceTo(params.dir)
    local x = params.x or FieldManager:getCharacterX()
    app.session:request("pb_map.C2S_MineBattle",
        {battltID = tonumber(params.battleId),faceTo = faceTo,MineID = params.mineId,PosX = x},
        function(msg)
            if msg.ok and params.callback then
                self:resetDarkThunderTriggerTime()
                params.callback()
            end
        end,
        nil,
        function(err)
            FieldManager:stopTouch(false)
        end)
end

function BattleManager:storyBattleStart(params)
    -- 向服务器上报 停止移动
    -- FieldManager:saveAutoWayFindingParams()
    -- FieldManager:getMyCharacter():stopMove(true)
    self:noMove()

    local faceTo = self:getBattleFaceTo(params.dir)
    local x = params.x or FieldManager:getCharacterX()
    app.session:request("pb_map.C2S_StoryTaskBattle",
        {battltID = tonumber(params.battleId),faceTo = faceTo,MineID = params.mineId,PosX = x},
        function(msg)
            if msg.ok then
                self:resetDarkThunderTriggerTime()
                if params.callback then
                    params.callback()
                end
            end
        end,
        nil,
        function(err)
            FieldManager:stopTouch(false)
        end)
end

-- 灰烬入侵 开始战斗
function BattleManager:grayBattleStart(params)
    -- 向服务器上报 停止移动
    -- FieldManager:saveAutoWayFindingParams()
    -- FieldManager:getMyCharacter():stopMove(true)
    self:noMove()

    local faceTo = self:getBattleFaceTo(params.dir)
    local x = params.x or FieldManager:getCharacterX()
    app.session:request("pb_map.C2S_GrayBattle",
        {battltID = tonumber(params.battleId),faceTo = faceTo,MineID = params.mineId,PosX = x},
        function(msg)
            if msg.ok and params.callback then
                self:resetDarkThunderTriggerTime()
                params.callback()
            end
        end,
        nil,
        function(err)
            FieldManager:stopTouch(false)
        end)
end

-- 训练场中
function BattleManager:isTraining()
    if self:isInBattle() and self:getEnterBattleType() == Enums.EBattleType.BtType_Training then
        return true
    end
    return false
end

function BattleManager:reqTraining(type)
    --这个消息通知服务器开始，然后服务器通知切地图
    self:noMove()
    self._lastTrainingModel = type
    app.session:request("pb_training.C2S_Training_Start",
        {typ = type or (self._lastTrainingModel or 0)},
        function(msg) end, 
        nil, 
        function(err) 
            FieldManager:stopTouch(false)
        end)
end

function BattleManager:reqTrainingAfterIntoMap()
    --上面消息发送后，服务器通知切地图完成，通知服务器开启cosplayView
    self:noMove()
    app.session:request("pb_pvploading.C2S_PVPLoadingFinish",
        {targetID = Enums.TeamTarget.training},
        function(msg) end, 
        nil, 
        function(err) 
            FieldManager:stopTouch(false)
        end)
end

function BattleManager:reqTrainingEscape()
    app.session:request("pb_training.C2S_Training_Escape", 
        {}, 
        function(msg) end)
end

function BattleManager:setNeedReEnterTraining(need)
    self._isNeedTraining = need
end

function BattleManager:getNeedReEnterTraining()
    return self._isNeedTraining or false
end

function BattleManager:setLastTrainingModel(type)
    self._lastTrainingModel = type
end

function BattleManager:getLastTrainingModel(type)
    return self._lastTrainingModel
end

function BattleManager:setTrainingRolePlayId(id)
    self._trainingRolePlayId = id
end

function BattleManager:getTrainingRolePlayId()
    return self._trainingRolePlayId or 0
end

-- 英雄之路开始战斗
function BattleManager:roadOfHeroBattleStart(params)
    -- 向服务器上报 停止移动
    -- FieldManager:saveAutoWayFindingParams()
    -- FieldManager:getMyCharacter():stopMove(true)
    self:noMove()

    local faceTo = self:getBattleFaceTo(params.dir)
    local x = params.x or FieldManager:getCharacterX()
    app.session:request("pb_roadOfHero.C2S_RoadOfHeroBattle",
        {ID = tonumber(params.id), FaceTo = faceTo, PosX = x},
        nil,
        nil,
        function(err) 
            FieldManager:stopTouch(false)
        end)
end

--function BattleManager:C2S_GetMineRequest(taskId,mineId)
--    if not taskId then return end
--
--    -- 检查自己当前是否为 跟随模式
--    if TeamModel:isWithTeam() then return end
--
--    app.session:request("pb_mine.C2S_GetMine",{taskID = taskId,mineID = mineId},function(msg)
--        if msg and msg.BattleID and msg.BattleID ~= 0 then
--            self:mineBattleStart({battleId = msg.BattleID,mineId = mineId})
--        end
--    end,{block = false},function(msg)
--
--    end)
--end

function BattleManager:bountyTaskBattle(taskId)
    if not taskId then return end

    -- 检查自己当前是否为 跟随模式
    if TeamModel:isWithTeam() then return end

    -- 向服务器上报 停止移动
    -- FieldManager:saveAutoWayFindingParams()
    -- FieldManager:getMyCharacter():stopMove(true)
    self:noMove()

    local faceTo = self:getBattleFaceTo()
    local x = FieldManager:getCharacterX()
    app.session:request("pb_map.C2S_CycleMineBattle",
        {TaskID = taskId, faceTo = faceTo, PosX = x},
        function(msg)
            if msg.ok then
                self:resetDarkThunderTriggerTime()
            end
        end,
        nil,
        function(err)
            FieldManager:stopTouch(false)
        end)
end

function BattleManager:handleBattleError(msg)
    if not msg or not msg.ok then
        StoryManager:clearTransferStatus()
    end
    -- if msg and msg.errcode then
    --     StoryManager:clearTransferStatus()
    --     app:popMessage(msg.errcode)
    -- end
end

function BattleManager:setSingleIndex(idx)
    self.singleModeIndex = idx
end

function BattleManager:GetSingleIndex()
    return self.singleModeIndex
end

--  simulate S2C_Start
function BattleManager:SimulateBattle(classTemp)
    local descStr = "res/battleGuideDesc/testdesc"
    if classTemp then
        descStr = descStr .. "_" .. classTemp
    end
    self.singleModeStartRawData = self:readfile(descStr)
    if nil == self.singleModeStartRawData then
        printInfo("Cannot find self.singleModeStartRawData")
        return
    end
    local descmsg = protobuf.decode("battle2.S2C_Start", self.singleModeStartRawData)
    protobuf.extract(descmsg)
    self.singleModeStartMsg = descmsg

    local newMsg = {}
    newMsg.authCode = "F75E3565"
    newMsg.battleType = Enums.EBattleType.BtType_Normal
    newMsg.formationID = descmsg.desc.formationId
    newMsg.id = descmsg.desc.battleId
    newMsg.mapId = 102
    newMsg.posX = 0
    newMsg.url = "192.168.10.224:9081"

    for i, v in ipairs(descmsg.desc.units) do
        if v.kind == "UnitKind_Player" and v.userBaseInfo.uid > 0 then
            self:setSingleIndex(i)
        end
    end

    self.flagSingleMode = true
    self.typeSingleStartData = Enums.SingleStartDataType.File
    self.flagSingleNeedVerify = false
    self.flagEscapeInSingleMode = false
    self.pauseBattleTime = 0
    self.pauseBattleDelta = 0
    self._enterBattleInfo = BattleInfoNormal.new(newMsg)
    self:prepareBattle()
end

function BattleManager:onParseEnterBattle(msg, bWaiting)
    self._enterBattleInfo = BattleInfoNormal.new(msg)
    if not bWaiting then
        self:prepareBattle()
    end
end

function BattleManager:onParseEnterSingleBattle(msg, rawData)
    self.singleModeStartRawData = rawData
    self.singleModeStartMsg = msg
    local newMsg = {}
    newMsg.authCode = "F75E3565"
    newMsg.battleType = protobuf.enum_id("battle2.EBattleType", msg.desc.btType)
    newMsg.formationID = msg.desc.formationId
    newMsg.id = msg.desc.battleId
    newMsg.mapId = 102
    newMsg.posX = 0
    newMsg.url = "192.168.10.224:9081"

    for i, v in ipairs(msg.desc.units) do
        if v.kind == "UnitKind_Player" and v.userBaseInfo.uid > 0 then
            self:setSingleIndex(i)
        end
    end

    self.flagSingleMode = true
    self.typeSingleStartData = Enums.SingleStartDataType.Proto
    self.flagSingleNeedVerify = true
    self.flagEscapeInSingleMode = false
    self.pauseBattleTime = 0
    self.pauseBattleDelta = 0
    self._enterBattleInfo = BattleInfoNormal.new(newMsg)
    self:prepareBattle()
end

function BattleManager:createCommandFromServerCommand(serverCommand)
    -- print("-----actualTime:",serverCommand.actualTime)
    -- print("-----seq:",serverCommand.seq)
    --print("-----cmdId:",serverCommand.cmdId)
    -- print("-----unitId:",serverCommand.unitId)
    -- print("-----skillId:",serverCommand.skillId)
    -- print("-----targetType:",serverCommand.targetType)
    -- print("-----targetValue:",serverCommand.targetValue)
    --print("-----content:",serverCommand.content)
    local cmdId = protobuf.enum_id("battle2.CmdID",serverCommand.cmdId)
    --print("---enum_id--cmdId:",cmdId)
    local targetType = 0
    if serverCommand.targetType then
        targetType = protobuf.enum_id("battle2.TargetType",serverCommand.targetType)
    end
    local command = battle.Command:create(
        serverCommand.unitId,
        serverCommand.seq or 0,--todo 不是自己的command需不需要改为0
        cmdId,
        serverCommand.skillId or 0,
        targetType, --1 目标类型为id
        serverCommand.targetValue or 0,
        -- serverCommand.clientTime or 0,
        0,
        serverCommand.actualTime or 0,
        serverCommand.content or "",
        serverCommand.flagId or 0,
        serverCommand.InstanceID or 0,
        serverCommand.BuyItemID or 0,
        serverCommand.BuyNum or 0,
        serverCommand.interactionType or 0,
        #(serverCommand.ms) or 0,
        serverCommand.subSkillId or 0
    )

    local monsterInfo
    for i = 1, #(serverCommand.ms) do
        monsterInfo = serverCommand.ms[i]
        command:setMonster(i-1, monsterInfo.monid, monsterInfo.pos)
    end

    return command
end

local	writablePath = cc.FileUtils:getInstance():getWritablePath().."/".."battleTest"
local	isDirectoryCreated = false
local	endDirectory = writablePath.."/records"

function BattleManager:pushFrameCommands(battleCore, commands, curTime)
	local removeIndex = {}
	for i,cmd in ipairs(commands) do
		if Command_getActualTime(cmd) <= curTime then
			if math.random(1000) < 900 then
			--if true then
				BattleCore_enqueue(battleCore, cmd)
				table.insert(removeIndex, 1)
			else
				--print("delay command----------")
				break
			end
		end
	end
	for i,index in ipairs(removeIndex) do
		table.remove(commands, index)
	end
end

function BattleManager:pushAllCommands(battleCore, commands)
	for i,cmd in ipairs(commands) do
		BattleCore_enqueue(battleCore, cmd)
	end
	commandsLen = table.getn(commands)
	for i = 1, commandsLen+1, 1 do
		table.remove(commands, 1)
	end
end

local battleCore = nil
local backCommands = {}
local maxBattleTime = 0
local wonTeam = 0
local frameCount = 0
local battleId = 0

function BattleManager:onParseQuickBattleResult(msg, rawData)
	if not battleTest then
		--打印日志
		battleTest = true
		if not cc.FileUtils:getInstance():isDirectoryExist(endDirectory) then
			isDirectoryCreated = cc.FileUtils:getInstance():createDirectory(endDirectory)
		else
			isDirectoryCreated = true
		end
		battle.BattleLogger:getInstance():setLevel(16)
		battle.BattleLogger:getInstance():setOutputConsole(false)
		if isDirectoryCreated then
			battle.BattleLogger:getInstance():setWriteablePath(endDirectory)
		end
		battle.BattleLogger:getInstance():start()
	end

	local start_time = socket.gettime()
	local result = -1
	local battleVer = battle.BattleResConfig:getInstance():getBattleVersion()
	local battleConfigVer = battle.BattleConfig:getInstance():getChecksum()
	if msg.btVer==battleVer and msg.cfgVer==battleConfigVer then
		result = 0
	end
	if result == 0 or battleCore then
		collectgarbage("collect")
		--如果上次已经完成，生成battleCore，否则，继续跑上次未完成的战斗
		if battleCore == nil then
			battleCore = battle.BattleCreator:createBattleCoreByQuickBattle(rawData, string.len(rawData))
			battle.BattleCore.enableAI(battleCore, true)
			battle.BattleCore.enableClone(battleCore, true)
			print("msg.desc.formationId:"..msg.desc.formationId)
			print("msg.btlResult.userCommands num "..#msg.btlResult.userCommands..":"..msg.btlResult.frameCount)
			
			--推入所有指令
			backCommands = {}
			local command
			for i,cmd in ipairs(msg.btlResult.userCommands) do
				command = self:createCommandFromServerCommand(cmd)
				table.insert(backCommands, command)
			end
			command = nil
			--补充Cmd_syncTime
			local sumFrame = msg.btlResult.frameCount
			local backCommandsIndex = 1
			local curFrameTime
			local syncCmd
			for frame = 5, sumFrame-5, 10  do
				curFrameTime = frame * 50
				--后面还有指令,并且后面指令时间小于curFrameTime
				while ((backCommandsIndex <= table.getn(backCommands))and(Command_getActualTime(backCommands[backCommandsIndex]) < curFrameTime)) do
					backCommandsIndex = backCommandsIndex + 1
				end
				--插入指令,unitId不能为0
				syncCmd = battle.Command:create(1,0,Enums.CmdID.Cmd_SyncTime,0,0,0,0,curFrameTime,"",0,0,0,0,0,0,0)
				table.insert(backCommands, backCommandsIndex, syncCmd)
				backCommandsIndex = backCommandsIndex + 1
			end
			--运行战斗结果
			maxBattleTime = msg.desc.env.battleTime
			wonTeam = msg.btlResult.wonTeam
			frameCount = msg.btlResult.frameCount
			battleId = msg.desc.battleId
		else
			print("continue last battle")
		end
		--循环计算
		local progressResult
		for accumulator = 0, maxBattleTime+3000, 50 do
			--每战斗3s补充一个时间同步包
			local cur_time= socket.gettime()
			if cur_time - start_time > 5 then
				app.session:request("battle2.C2S_QuickBattleResult",{verifyResult = 2},function(ret)
				end)
				return
			end
			self:pushFrameCommands(battleCore, backCommands, BattleCore_getCurrentTime(battleCore))
			progressResult = BattleCore_progress(battleCore, 50)
			if ProgressResult_getFinished(progressResult) then
				--比较战斗结果
				--如果帧数或者winTeam有一个不一致，打印
				local battleResult = ProgressResult_getBattleResult(progressResult)
				print("battleResust:"..wonTeam..","..BattleResult_wonTeamId(battleResult)..":"
				..frameCount..","..BattleResult_frameCount(battleResult))
				if wonTeam == BattleResult_wonTeamId(battleResult) and 
				frameCount == BattleResult_frameCount(battleResult) then
					result = 1
				end
				break
			end
		end
		
		backCommands = nil
		battleCore:release()
		battleCore = nil
		collectgarbage("collect")
	end
	--验证失败成功
	if not (result == 1) then
		--移除日志文件
		local filename = writablePath.."/".."error.log";
		print(filename)
		local file = io.open(filename,"a")
		if file then
			print("open error.log")
			file:write(battleId.."_battle.log\n")
			file:close()
		end
		print("remove file:"..filename)
	end
	print("+++++++++++++onParseQuickBattleResult:"..result)
	local end_time= socket.gettime()	
	local use_time = end_time - start_time
	if use_time < 0.05 then
		socket.select(nil, nil, 0.05)
	end
	--发送回包到game
	app.session:request("battle2.C2S_QuickBattleResult",{verifyResult = result},function(ret)
	end)
end

function BattleManager:isSingleModeNeedVerify()
    return self.flagSingleNeedVerify
end

function BattleManager:setEnterBattleInfo(info)
    self._enterBattleInfo = info
end

function BattleManager:getEnterBattleInfo()
    return self._enterBattleInfo
end

function BattleManager:updateBattle(dt)
    if cc.isAlive(self.mBattleController) and (not self.pauseBattleFlag) then
        self.mBattleController:tick_(dt)
    end
end

function BattleManager:pauseBattle(flagGuidePause)
    if self.flagGuidePause then
        return
    end
    if self:isInBattle() and self:isSingleMode() and (not self.pauseBattleFlag) then
        self.pauseBattleTime = app:getTime()
        self.pauseBattleFlag = true
        self.flagGuidePause = flagGuidePause
        if cc.isAlive(self.mBattleController) then
            self.mBattleController:setEnginePauseState(true)
        end
    end
end

function BattleManager:resumeBattle(flagGuidePause)
    if self.flagGuidePause and not flagGuidePause then
        return
    end
    if self:isInBattle() and self:isSingleMode() and self.pauseBattleFlag then
        self.pauseBattleDelta = app:getTime() - self.pauseBattleTime
        self.pauseBattleFlag = false
        self.flagGuidePause = false
        if cc.isAlive(self.mBattleController) then
            self.mBattleController:setEnginePauseState(false)
        end
    end
end

function BattleManager:countDarkThunderBattlePoints(task, opt)
    if not task then return end
    if task:isTaken() and opt == "insert" then
        local battlePoints = TaskManager:getDarkThunderBattlePoints(task)
        if battlePoints then
            if not self._taskDarkThunderBattlePoints then
                self._taskDarkThunderBattlePoints = {}
            end
            if not self._taskDarkThunderBattlePoints[task:getId()] then
                self._taskDarkThunderBattlePoints[task:getId()] = {}
                for _,v in pairs(battlePoints) do
                    table.insert(self._taskDarkThunderBattlePoints[task:getId()],v)
                end
            end
        end
    elseif opt == "update" and task:isFinished() and self._taskDarkThunderBattlePoints then
        self._taskDarkThunderBattlePoints[task:getId()] = nil
    elseif opt == "delete" and self._taskDarkThunderBattlePoints then
        self._taskDarkThunderBattlePoints[task:getId()] = nil
    end
end

function BattleManager:resetDarkThunderTriggerTime()
    for _, taskBattlePoints in pairs(self._taskDarkThunderBattlePoints) do
        for _, battlePoint in ipairs(taskBattlePoints) do
            if battlePoint.mapId == MapManager:getMapId() then
                battlePoint.moveTime = 0
            end
        end
    end
end

function BattleManager:updateDarkThunderBattle(dt)
    if self:isInBattle() then return end
    if not self._taskDarkThunderBattlePoints then return end
    local character = FieldManager:getMyCharacter()
    if cc.isDead(character) then return end
    local cx = MathFloor(NodeGetPositionXFunc(character))

    for _, battlePoints in pairs(self._taskDarkThunderBattlePoints) do
        local flag = false
        for i,v in ipairs(battlePoints) do
            if v.mapId == MapManager:getMapId()
                and cx >= v.lx
                and cx <= v.rx then
                if v.moveTime >= v.time then
                    v.moveTime = 0
--                    self:C2S_GetMineRequest(v.taskId,v.mine)
                    -- self:bountyTaskBattle(v.taskId)
                    flag = true
                    break
                elseif character:isMove() then
                    v.moveTime = v.moveTime + dt * 1000
                end
            end
        end
        if flag then break end
    end
end

function BattleManager:getEnterBattleType()
    if self._enterBattleInfo then
        return self._enterBattleInfo:getBattleType()
    else
        return Enums.EBattleType.BtType_Normal
    end
end

function BattleManager:isBattleUsingArenaAvatar()
    if self._enterBattleInfo then
        return self._enterBattleInfo:isUsingArenaAvatar()
    else
        return false
    end
end

function BattleManager:setClientWeakEndCBId(id)
    self._cronsIdx = id
end

function BattleManager:clearClientWeakEndCB()
    if self._cronsIdx then
        scheduler.cancelCron(self._cronsIdx)
        self._cronsIdx = nil
    end
end
return BattleManager
